/**
 * @Author: DengLibin
 * @Date: Create in 2023-01-06 15:56:17
 * @Description: crud
 */
package gormdb

import (
	"fmt"

	"gorm.io/gorm"
)

type TableEntity interface {
	TableName() string
}

/**
 * @Author: DengLibin
 * @Date: Create in 2023-01-06 16:06:15
 * @Description:  执行原生sql
 */
func ExecuteSql(db *gorm.DB, inTx bool, sql string, values ...interface{}) (int64, error) {
	var rowsAffected int64

	//在事务中执行
	if inTx {
		err := ExecInTx(db, func(tx *gorm.DB) error {
			//返回任何错误都会回滚事务
			result := tx.Exec(sql, values...)
			rowsAffected = result.RowsAffected
			return result.Error
		})
		return rowsAffected, err

	}
	result := db.Exec(sql, values...)
	return result.RowsAffected, result.Error
}

/**
 * @Author: DengLibin
 * @Date: Create in 2023-01-09 11:25:34
 * @Description: 在事务中执行
 */
func ExecInTx(db *gorm.DB, fun func(tx *gorm.DB) error) error {
	return db.Transaction(func(tx *gorm.DB) error {
		return fun(tx)
	})
}

/**
 * @Author: DengLibin
 * @Date: Create in 2023-01-09 10:08:13
 * @Description: sql查询  "select id,name from user where id=?" 5
 */
func QueryBySql(db *gorm.DB, emptySlicePtr interface{}, sql string, values ...interface{}) (int64, error) {

	result := db.Raw(sql, values...).Scan(emptySlicePtr)

	return result.RowsAffected, result.Error
}

/**
 * @Author: DengLibin
 * @Date: Create in 2023-01-09 10:28:56
 * @Description: 原生sql分页查询 返回总数 使用limit 和offset语法
 */
func QueryPageBySqlUseLimitOffset(db *gorm.DB, emptySlicePtr interface{}, page int, size int,
	sql string, values ...interface{}) (int64, error) {

	var total int64
	countSql := "SELECT COUNT(1) FROM (" + sql + ")"
	db.Raw(countSql, values...).Scan(&total)

	pageSql := fmt.Sprintf(sql+"  limit %d   OFFSET %d", size, (page-1)*size)

	result := db.Raw(pageSql, values...).
		Scan(emptySlicePtr)

	return total, result.Error
}

/**
 * @Author: DengLibin
 * @Date: Create in 2023-01-06 16:13:55
 * @Description: 添加一条记录
 * @db
 * @tableName 表名
 * @entityPtr 结构体指针
 */
func InsertOne(db *gorm.DB, entityPtr TableEntity) (int64, error) {
	result := db.Table(entityPtr.TableName()).Create(entityPtr)
	return result.RowsAffected, result.Error
}

/**
 * @Author: DengLibin
 * @Date: Create in 2023-01-09 09:24:20
 * @Description: 批量插入
 */
func InsertBatch(db *gorm.DB, tableName string, slice interface{}) (int64, error) {

	//每批次大小为100
	result := db.Table(tableName).CreateInBatches(slice, 100)
	return result.RowsAffected, result.Error
}

/**
 * @Author: DengLibin
 * @Date: Create in 2023-01-06 16:22:22
 * @Description: 根据id查询
 */
func QueryById(db *gorm.DB, id int32, emptyPtr TableEntity) (int64, error) {
	result := db.Table(emptyPtr.TableName()).
		Select("*"). //只查询指定字段
		Limit(1).
		Find(emptyPtr, id)
		//SELECT * FROM `User` WHERE `User`.`ID` = 1 LIMIT 1
	return result.RowsAffected, result.Error

}

/**
 * @Author: DengLibin
 * @Date: Create in 2023-01-09 09:45:21
 * @Description: id in 查询
 */
func QueryByIds(db *gorm.DB, tableName string, emptySlicePtr interface{}, ids []int) (int64, error) {
	result := db.Table(tableName).Find(emptySlicePtr, ids)
	if result.Error != nil {
		panic(result.Error)
	}
	return result.RowsAffected, result.Error
}

/**
 * @Author: DengLibin
 * @Date: Create in 2023-01-09 09:51:52
 * @Description: 查询所有
 */
func QueryAll(db *gorm.DB, tableName string, emptySlicePtr interface{}) (int64, error) {
	result := db.Table(tableName).Find(emptySlicePtr)

	return result.RowsAffected, result.Error
}

/**
 * @Author: DengLibin
 * @Date: Create in 2023-01-09 10:02:57
 * @Description: 分页查询 返回总数
 */
func QueryPage(db *gorm.DB, tableName string, emptySlicePtr interface{}, page int, size int) (int64, error) {
	db = db.Table(tableName)
	var total int64
	//总数
	db.Count(&total)

	// 查分页数据
	result := db.Limit(size).
		Offset((page - 1) * size).
		//Order("id asc").
		Find(emptySlicePtr)

	return total, result.Error
}

/**
 * @Author: DengLibin
 * @Date: Create in 2023-01-09 09:56:38
 * @Description: 条件查询 如果想要包含查询条件，你可以使用 map，其会包含所有 key-value 的查询条件
 */
func QueryByMap(db *gorm.DB, tableName string, emptySlicePtr interface{}, params map[string]interface{}) (int64, error) {
	result := db.Table(tableName).
		Where(params).
		//Order("id asc").
		Find(emptySlicePtr)
	return result.RowsAffected, result.Error
}

/**
 * @Author: DengLibin
 * @Date: Create in 2023-01-09 10:53:31
 * @Description: 根据id更新 没有值的字段会忽略
 */
func UpdateById(db *gorm.DB, entityPtr TableEntity, idColumName string, id interface{}) (int64, error) {

	result := db.Table(entityPtr.TableName()).
		Where(idColumName+" = ?", id).
		Updates(entityPtr)

	return result.RowsAffected, result.Error
}

/**
 * @Author: DengLibin
 * @Date: Create in 2023-01-09 10:53:31
 * @Description: 根据id更新 没有值的字段会忽略
 */
func UpdateByID(db *gorm.DB, entityPtr TableEntity, id interface{}) (int64, error) {

	result := db.Table(entityPtr.TableName()).
		Where("ID = ?", id).
		Updates(entityPtr)

	return result.RowsAffected, result.Error
}

/**
 * @Author: DengLibin
 * @Date: Create in 2023-01-09 10:53:31
 * @Description: 根据id删除
 * @param
 * @param entityPtr 结构体 带id字段
 */
func DeleteById(db *gorm.DB, entityPtr TableEntity) (int64, error) {

	result := db.Table(entityPtr.TableName()).
		Delete(entityPtr)

	return result.RowsAffected, result.Error
}

/**
 * @Author: DengLibin
 * @Date: Create in 2023-01-09 10:53:31
 * @Description: 根据参数更新 没有值的字段会忽略
 */
func UpdateByParam(db *gorm.DB, entityPtr TableEntity, param map[string]interface{}) (int64, error) {

	result := db.Table(entityPtr.TableName()).
		Where(param).
		Updates(entityPtr)

	return result.RowsAffected, result.Error
}
